Android 為了讓我們開發方便,提供了多樣的 Component 方便各種 UI 的需求。這些 Component 在處理一些複雜的 UI 需求會有一些需要注意的效能問題。這一篇我們就以 RecyclerView 為例來介紹效能優化。
當 RecyclerView 的資料來源有異動時,一般會使用notifyDataSetChanged
來通知資料有異動,RecyclerView 便能更新畫面。但如果只是少部分的資料異動時,RecyclerView 也提供部分更新項目的功能。例如只是新增一筆資料,是不需要將所有資料重新繫結的。RecyclerView 提供了這幾個方法讓你只更新有異動的部分。
//依position 新增項目
adapter.notifyItemInserted(position)
//依position 移除項目
adapter.notifyItemRemoved(position)
//更新position項目
adapter.notifyItemChanged(position)
//更新一個範圍
adapter.notifyItemRangeInserted(start, end)
使用 Glide 載入圖片
載入圖片需要花費較多資源,在多筆資料呈現就需要注意效能問題。在這個系列已多次的提到使用 Glide 載入圖片,提供延遲載入及Cache等功能。不管你的圖片是存放在 App 裡還是從網址請求圖片,都直接使用像 Glide 這樣的圖片載入套件。
讓圖片高度固定
在 RecyclerView 的每一個 Item 中,如果有使用到圖片,儘量讓圖片高度固定。
確認圖片的大小
檔案太大的圖片將影響效能,確認圖片的大小是否經過最佳化。
onBindViewHolder 不要做太多事
在 onBindViewHolder
應只處理跟這個 Item 的 UI 繫結有關的事,也就是只會傳資料進來繫結,不在這裡處理太多無關的事。例如要設定事件OnClickListener
就應該在onCreateViewHolder
處理而不是onBindViewHolder
。
class MainAdapter(private val names:List<String>) :RecyclerView.Adapter<RecyclerView.ViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val name = names[position]
(holder as ItemViewHolder).setName(name)
}
override fun getItemCount(): Int {
return names.count()
}
}
這篇舉了一個比較容易有效能問題的 RecyclerView 來介紹。Android 有許多的 Component 幫助我們方便做出複雜功能的 UI。在 Android 的官方 Guildeline 大多會有詳細的介紹,請在使用前熟悉使用方式,避免錯誤使用造成效能問題。